Skip to content

chore: Describe RBAC rules, remove unnecessary rules#674

Merged
NickLarsenNZ merged 15 commits intomainfrom
chore/rbac-review
Apr 8, 2026
Merged

chore: Describe RBAC rules, remove unnecessary rules#674
NickLarsenNZ merged 15 commits intomainfrom
chore/rbac-review

Conversation

@NickLarsenNZ
Copy link
Copy Markdown
Member

@NickLarsenNZ NickLarsenNZ commented Mar 25, 2026

Part of stackabletech/issues#798

Note

This was initially generated by a coding assistant to see how well it can inspect code and review the RBAC rules. the changes will be properly checked before reviews are requested.

  • Document each rule
  • Check the docs make sense. Rewrite where necessary
  • Remove unnecessary permissions
  • Attach explanations to PR description
  • Run all tests
  • Split operator and product roles into separate files Already split

Rules Removed in This Branch

Operator ClusterRole (roles.yaml)

  • nodes list+watch - only nodes/proxy get is needed for cluster domain detection
  • persistentvolumeclaims - entire rule removed; the operator doesn't manage PVCs directly
  • endpoints - removed; no references in the operator code, was a copy-paste inclusion
  • statefulsets rule: deployments resource removed - no references in the operator code, was a copy-paste inclusion
  • customresourcedefinitions get verb - list+watch are always present; create+patch remain conditional
  • security.openshift.io/securitycontextconstraints use - copy-paste error; only the product pods need this
  • secrets - entire resource removed; the operator references secrets by name in pod specs (secret class volumes, image pull secrets) but never calls the Kubernetes API to get/create/manage Secret objects directly - the secret-operator handles that
  • deletecollection removed from all rules - orphan cleanup uses individual deletes, not bulk deletes; no references in the operator code
  • create and patch removed from pods - the operator only watches and deletes driver pods; it creates Jobs and StatefulSets which in turn create pods
  • update verb removed from all rules - the operator exclusively uses Server-Side Apply (patch); update (HTTP PUT) is never called
  • watch removed from rolebindings, poddisruptionbudgets, listeners - none of these are registered with .owns() so no controller sets up a watch on them
  • watch, delete, get, list removed from jobs - Jobs are only created via SSA; never tracked for orphan cleanup or watched. Job completion is detected by the pod-driver controller watching driver pods for terminal phases (Succeeded/Failed), not by watching the Job itself. Cleanup of the Job and its pods is left to Kubernetes TTL (ttlSecondsAfterFinished) or manual action.
  • patch removed from sparkapplications, sparkhistoryservers, sparkconnectservers, sparkapptemplates - the operator only patches their /status subresources, not the main resources

Spark Driver + Connect Server ClusterRoles

  • serviceaccounts resource - Spark uses an existing ServiceAccount for executors but doesn't create them
  • events.k8s.io create rule removed - not used

History Server ClusterRole

  • Entire core API rule removed: configmaps, persistentvolumeclaims, pods, secrets, serviceaccounts, services (all verbs) - the History Server reads event logs from S3/HDFS via mounted volumes and makes no Kubernetes API calls at runtime
  • events.k8s.io create rule removed - same reason

NickLarsenNZ

This comment was marked as resolved.

@NickLarsenNZ

This comment was marked as resolved.

@NickLarsenNZ
Copy link
Copy Markdown
Member Author

--- PASS: kuttl/harness/spark-history-server_openshift-false_spark-3.5.8_s3-use-tls-true (314.21s)
--- PASS: kuttl/harness/custom-log-directory_openshift-false_spark-3.5.7_hdfs-latest-3.4.2_zookeeper-latest-3.9.4 (269.45s)
--- PASS: kuttl/harness/custom-log-directory_openshift-false_spark-3.5.8_hdfs-latest-3.4.2_zookeeper-latest-3.9.4 (281.92s)
--- PASS: kuttl/harness/custom-log-directory_openshift-false_spark-4.0.1_hdfs-latest-3.4.2_zookeeper-latest-3.9.4 (242.85s)
--- PASS: kuttl/harness/custom-log-directory_openshift-false_spark-4.1.1_hdfs-latest-3.4.2_zookeeper-latest-3.9.4 (303.51s)
--- PASS: kuttl/harness/delta-lake_openshift-false_spark-delta-lake-3.5.7 (303.03s)
--- PASS: kuttl/harness/delta-lake_openshift-false_spark-delta-lake-3.5.8 (352.19s)
--- PASS: kuttl/harness/delta-lake_openshift-false_spark-delta-lake-4.0.1 (208.81s)
--- PASS: kuttl/harness/hbase-connector_openshift-false_spark-hbase-connector-3.5.7_hbase-2.6.4_hdfs-latest-3.4.2_zookeeper-latest-3.9.4 (288.17s)
--- PASS: kuttl/harness/hbase-connector_openshift-false_spark-hbase-connector-3.5.8_hbase-2.6.4_hdfs-latest-3.4.2_zookeeper-latest-3.9.4 (334.14s)
--- PASS: kuttl/harness/iceberg_openshift-false_spark-iceberg-3.5.7 (103.45s)
--- PASS: kuttl/harness/iceberg_openshift-false_spark-iceberg-3.5.8 (89.25s)
--- PASS: kuttl/harness/iceberg_openshift-false_spark-iceberg-4.0.1 (58.07s)
--- PASS: kuttl/harness/logging_openshift-false_spark-logging-3.5.7_ny-tlc-report-0.3.0 (422.37s)
--- PASS: kuttl/harness/logging_openshift-false_spark-logging-3.5.8_ny-tlc-report-0.3.0 (423.31s)
--- PASS: kuttl/harness/logging_openshift-false_spark-logging-4.0.1_ny-tlc-report-0.3.0 (339.00s)
--- PASS: kuttl/harness/logging_openshift-false_spark-logging-4.1.1_ny-tlc-report-0.3.0 (348.16s)
--- PASS: kuttl/harness/overrides_openshift-false_spark-3.5.7 (153.31s)
--- PASS: kuttl/harness/overrides_openshift-false_spark-3.5.8 (150.52s)
--- PASS: kuttl/harness/overrides_openshift-false_spark-4.0.1 (123.87s)
--- PASS: kuttl/harness/overrides_openshift-false_spark-4.1.1 (181.26s)
--- PASS: kuttl/harness/pyspark-ny-public-s3_openshift-false_spark-3.5.7 (191.11s)
--- PASS: kuttl/harness/pyspark-ny-public-s3_openshift-false_spark-3.5.8 (196.93s)
--- PASS: kuttl/harness/pyspark-ny-public-s3_openshift-false_spark-4.0.1 (131.39s)
--- PASS: kuttl/harness/pyspark-ny-public-s3_openshift-false_spark-4.1.1 (118.92s)
--- PASS: kuttl/harness/pyspark-ny-public-s3-image_openshift-false_spark-3.5.7_ny-tlc-report-0.3.0 (184.39s)
--- PASS: kuttl/harness/pyspark-ny-public-s3-image_openshift-false_spark-3.5.8_ny-tlc-report-0.3.0 (161.26s)
--- PASS: kuttl/harness/pyspark-ny-public-s3-image_openshift-false_spark-4.0.1_ny-tlc-report-0.3.0 (130.88s)
--- PASS: kuttl/harness/pyspark-ny-public-s3-image_openshift-false_spark-4.1.1_ny-tlc-report-0.3.0 (144.11s)
--- PASS: kuttl/harness/resources_openshift-false_spark-3.5.7 (92.83s)
--- PASS: kuttl/harness/resources_openshift-false_spark-3.5.8 (122.97s)
--- PASS: kuttl/harness/resources_openshift-false_spark-4.0.1 (55.30s)
--- PASS: kuttl/harness/resources_openshift-false_spark-4.1.1 (61.29s)
--- PASS: kuttl/harness/smoke_openshift-false_spark-3.5.7_s3-use-tls-false (191.35s)
--- PASS: kuttl/harness/smoke_openshift-false_spark-3.5.7_s3-use-tls-true (195.79s)
--- PASS: kuttl/harness/smoke_openshift-false_spark-3.5.8_s3-use-tls-false (199.10s)
--- PASS: kuttl/harness/smoke_openshift-false_spark-3.5.8_s3-use-tls-true (181.37s)
--- PASS: kuttl/harness/smoke_openshift-false_spark-4.0.1_s3-use-tls-false (172.62s)
--- PASS: kuttl/harness/smoke_openshift-false_spark-4.0.1_s3-use-tls-true (165.57s)
--- PASS: kuttl/harness/smoke_openshift-false_spark-4.1.1_s3-use-tls-false (405.85s)
--- PASS: kuttl/harness/smoke_openshift-false_spark-4.1.1_s3-use-tls-true (171.64s)
--- PASS: kuttl/harness/spark-connect_openshift-false_spark-connect-3.5.7_s3-use-tls-false (217.98s)
--- PASS: kuttl/harness/spark-connect_openshift-false_spark-connect-3.5.7_s3-use-tls-true (253.97s)
--- PASS: kuttl/harness/spark-connect_openshift-false_spark-connect-3.5.8_s3-use-tls-false (139.29s)
--- PASS: kuttl/harness/spark-connect_openshift-false_spark-connect-3.5.8_s3-use-tls-true (238.79s)
--- PASS: kuttl/harness/spark-connect_openshift-false_spark-connect-4.0.1_s3-use-tls-false (202.00s)
--- PASS: kuttl/harness/spark-connect_openshift-false_spark-connect-4.0.1_s3-use-tls-true (201.90s)
--- PASS: kuttl/harness/spark-connect_openshift-false_spark-connect-4.1.1_s3-use-tls-false (202.68s)
--- PASS: kuttl/harness/spark-connect_openshift-false_spark-connect-4.1.1_s3-use-tls-true (207.81s)
--- PASS: kuttl/harness/spark-examples_openshift-false_spark-3.5.7 (57.14s)
--- PASS: kuttl/harness/spark-examples_openshift-false_spark-3.5.8 (69.57s)
--- PASS: kuttl/harness/spark-examples_openshift-false_spark-4.0.1 (63.36s)
--- PASS: kuttl/harness/spark-examples_openshift-false_spark-4.1.1 (58.39s)
--- PASS: kuttl/harness/spark-history-server_openshift-false_spark-3.5.7_s3-use-tls-false (273.19s)
--- PASS: kuttl/harness/spark-history-server_openshift-false_spark-3.5.7_s3-use-tls-true (301.06s)
--- PASS: kuttl/harness/spark-history-server_openshift-false_spark-3.5.8_s3-use-tls-false (267.47s)
--- PASS: kuttl/harness/spark-history-server_openshift-false_spark-4.0.1_s3-use-tls-false (173.53s)
--- PASS: kuttl/harness/spark-history-server_openshift-false_spark-4.0.1_s3-use-tls-true (319.34s)
--- PASS: kuttl/harness/spark-history-server_openshift-false_spark-4.1.1_s3-use-tls-false (212.04s)
--- PASS: kuttl/harness/spark-history-server_openshift-false_spark-4.1.1_s3-use-tls-true (210.65s)
--- PASS: kuttl/harness/spark-ny-public-s3_openshift-false_spark-3.5.7_s3-use-tls-false (173.19s)
--- PASS: kuttl/harness/spark-ny-public-s3_openshift-false_spark-3.5.7_s3-use-tls-true (181.17s)
--- PASS: kuttl/harness/spark-ny-public-s3_openshift-false_spark-3.5.8_s3-use-tls-false (417.50s)
--- PASS: kuttl/harness/spark-ny-public-s3_openshift-false_spark-3.5.8_s3-use-tls-true (184.74s)
--- PASS: kuttl/harness/spark-ny-public-s3_openshift-false_spark-4.0.1_s3-use-tls-false (138.58s)
--- PASS: kuttl/harness/spark-ny-public-s3_openshift-false_spark-4.0.1_s3-use-tls-true (135.03s)
--- PASS: kuttl/harness/spark-ny-public-s3_openshift-false_spark-4.1.1_s3-use-tls-false (128.15s)
--- PASS: kuttl/harness/spark-ny-public-s3_openshift-false_spark-4.1.1_s3-use-tls-true (150.87s)
--- PASS: kuttl/harness/spark-pi-private-s3_openshift-false_spark-3.5.7 (208.58s)
--- PASS: kuttl/harness/spark-pi-private-s3_openshift-false_spark-3.5.8 (149.75s)
--- PASS: kuttl/harness/spark-pi-private-s3_openshift-false_spark-4.0.1 (123.85s)
--- PASS: kuttl/harness/spark-pi-private-s3_openshift-false_spark-4.1.1 (126.13s)

@NickLarsenNZ NickLarsenNZ self-assigned this Apr 8, 2026
@NickLarsenNZ NickLarsenNZ moved this to Development: Waiting for Review in Stackable Engineering Apr 8, 2026
@NickLarsenNZ NickLarsenNZ requested a review from razvan April 8, 2026 07:48
@NickLarsenNZ NickLarsenNZ marked this pull request as ready for review April 8, 2026 07:48
Comment thread deploy/helm/spark-k8s-operator/templates/spark-connect-clusterrole.yaml Outdated
Comment thread deploy/helm/spark-k8s-operator/templates/spark-clusterrole.yaml Outdated
Copy link
Copy Markdown
Member

@razvan razvan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@NickLarsenNZ NickLarsenNZ added this pull request to the merge queue Apr 8, 2026
@NickLarsenNZ NickLarsenNZ moved this from Development: Waiting for Review to Development: Done in Stackable Engineering Apr 8, 2026
Merged via the queue into main with commit e1dd88b Apr 8, 2026
12 checks passed
@NickLarsenNZ NickLarsenNZ deleted the chore/rbac-review branch April 8, 2026 12:01
@lfrancke lfrancke moved this from Development: Done to Done in Stackable Engineering Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

3 participants